package se.nikmel.AnDisper.UI;

import java.util.List;

import se.nikmel.AnDisper.MainActivity;
import se.nikmel.AnDisper.R;
import se.nikmel.AnDisper.Application.Application;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class UI_AppLauncher_Controller implements I_UI_ViewController {
	// Misc
	private static final String TAG = "UI_AppLauncer"; // Logging tag
	private static final int ICON_SIZE = 128;
	private final int LAYOUT_ID = R.layout.scr_applications;
	//
	@SuppressWarnings("unused")
	private int m_iLayoutID;
	private MainActivity m_actParent;
	private String m_sLastUpdateServerIP;
	private OnDisperConnectionError m_oConnectionErrorListener;
	private _RefreshApplicationsTask m_tskRefresh;
	// UI elements
	private View m_scrAppLauncher;
	private GridView m_grdApps;
	private TextView m_txtTitle;
	private TextView m_txtServerName;
	private LinearLayout m_lnrTitle;

	public UI_AppLauncher_Controller(MainActivity p_actParent) {
		m_actParent = p_actParent;
		m_sLastUpdateServerIP = null;
		m_oConnectionErrorListener = null;
		m_tskRefresh = null;

		// Load the screen
		LayoutInflater oInflater = m_actParent.getLayoutInflater();
		m_scrAppLauncher = oInflater.inflate(LAYOUT_ID, null);
		m_lnrTitle = (LinearLayout) m_scrAppLauncher
				.findViewById(R.id.lnrAppsTitlebar);
		m_lnrTitle.setBackgroundColor(Color.DKGRAY);

		m_txtServerName = (TextView) m_scrAppLauncher
				.findViewById(R.id.txtAppServerName);
		m_txtServerName.setBackgroundColor(Color.TRANSPARENT);

		m_txtTitle = (TextView) m_scrAppLauncher.findViewById(R.id.txtAppTitle);
		m_txtTitle.setBackgroundColor(Color.TRANSPARENT);
		m_txtTitle.setShadowLayer(2.5f, 3.0f, 3.0f, Color.BLACK);

		m_grdApps = (GridView) m_scrAppLauncher.findViewById(R.id.grdApps);
		m_grdApps.setTouchDelegate(m_actParent.getTouchDelegate());
	}

	public View getView() {
		return m_scrAppLauncher;
	}

	public void pause() {
		// Cancel any refresh-tasks
		if (m_tskRefresh != null)
			m_tskRefresh.cancel(true);
	}

	public void resume() {
		// Only automatically refresh if first resume or on a new server
		if (m_sLastUpdateServerIP == null
				|| !m_sLastUpdateServerIP.equals(m_actParent.getDisperServer()
						.getServerIP()))
			refresh();
	}

	/*
	 * **************** PRIVATE METHODS
	 */

	public void setOnConectionErrorListener(OnDisperConnectionError p_oListener) {
		m_oConnectionErrorListener = p_oListener;
	}

	private void fireConnectionFailed(String p_sMessage) {
		if (m_oConnectionErrorListener != null)
			m_oConnectionErrorListener.onConnectionError(p_sMessage);
		else
			Log.w(TAG,
					"(WW) Disper connection error occured but no one listens (applications)...");
	}

	/**
	 * Updates the list of available apps from server
	 * 
	 * @return
	 */
	public void refresh() {
		if (m_tskRefresh == null) {
			m_tskRefresh = new _RefreshApplicationsTask();
			m_tskRefresh.execute((Void) null);
		}
	}

	private void setApps(List<Application> p_lstApps) {
		m_grdApps.setAdapter(new _ApplicationsAdapter(p_lstApps));
		m_grdApps.setHapticFeedbackEnabled(true);

		m_grdApps.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View v,
					int position, long id) {
				_ApplicationsAdapter oAdapter = (_ApplicationsAdapter) parent
						.getAdapter();
				final Application appSelected = oAdapter.getAppAt(position);

				// 1. Fråga om man är säker
				Builder dlgConfirmation = new AlertDialog.Builder(m_actParent);
				dlgConfirmation.setTitle("Launch?");
				ImageView imgIcon = new ImageView(m_actParent);
				imgIcon.setMinimumHeight(ICON_SIZE);
				imgIcon.setMinimumWidth(ICON_SIZE);
				imgIcon.setMaxHeight(ICON_SIZE);
				imgIcon.setMaxWidth(ICON_SIZE);
				imgIcon.setAdjustViewBounds(true);
				imgIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
				imgIcon.setImageURI(appSelected.getIcon());
				dlgConfirmation.setIcon(imgIcon.getDrawable());

				dlgConfirmation.setCancelable(false);
				dlgConfirmation
						.setNegativeButton(android.R.string.cancel, null);
				dlgConfirmation.setPositiveButton("Launch",
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int which) {
								Log.v(TAG, "Launching " + appSelected.getID());
								_LaunchApplicationTask tskLaunch = new _LaunchApplicationTask();
								tskLaunch.execute(appSelected);

							}
						});
				dlgConfirmation.create().show();
			}
		});
	}

	private class _RefreshApplicationsTask extends
			AsyncTask<Void, Void, Boolean> {

		private ProgressDialog m_uiProgress;
		private List<Application> m_lstApps;

		@Override
		protected Boolean doInBackground(Void... params) {
			m_lstApps = m_actParent.getDisperServer().getApplications();

			if (m_lstApps == null || this.isCancelled()) {
				return false;
			} else {
				return true;
			}
		}

		@Override
		protected void onCancelled() {
			m_uiProgress.dismiss();
			m_tskRefresh = null;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);

			m_tskRefresh = null;

			if (result) {
				setApps(m_lstApps);
				m_sLastUpdateServerIP = m_actParent.getDisperServer()
						.getServerIP();
				new _GetHostNameTask().execute((Void[]) null);
				m_txtServerName.setVisibility(View.VISIBLE);
			}
			m_uiProgress.dismiss();
			if (!result)
				fireConnectionFailed("Failed to retreive applications from server!");
		}

		@Override
		protected void onPreExecute() {
			m_uiProgress = ProgressDialog.show(m_actParent, "Updating...",
					"Requesting available applications from server", true);
			super.onPreExecute();
		}

	}

	private class _GetHostNameTask extends AsyncTask<Void, Void, String> {

		@Override
		protected String doInBackground(Void... params) {
			String sHostName = m_actParent.getDisperServer().getHostname();

			return sHostName;
		}
		
		@Override
		protected void onPostExecute(String p_sHostName) {
			m_txtServerName.setText(p_sHostName);
		}
	}

	private class _LaunchApplicationTask extends
			AsyncTask<Application, Void, Void> {

		@Override
		protected Void doInBackground(Application... params) {
			Application appToLaunch = params[0];
			m_actParent.getDisperServer().launchApp(appToLaunch);
			return (Void) null;
		}
	}

	/**
	 * Adapter for the gridview containing the applications
	 * 
	 * @author niklas
	 * 
	 */
	private class _ApplicationsAdapter extends BaseAdapter {
		private List<Application> m_lstApps;
		final float scale = m_actParent.getResources().getDisplayMetrics().density;
		private int m_iPaddingPixels;

		_ApplicationsAdapter(List<Application> p_lstApps) {
			m_lstApps = p_lstApps;
			m_iPaddingPixels = (int) (15 * scale + 0.5f);
		}

		public int getCount() {
			return m_lstApps.size();
		}

		public Object getItem(int arg0) {
			return m_lstApps.get(arg0);
		}

		public Application getAppAt(int p_iPosition) {
			return (Application) getItem(p_iPosition);
		}

		public long getItemId(int arg0) {
			// No idea what to do here...
			return 0;
		}

		public View getView(int p_iPosition, View convertView, ViewGroup parent) {
			LinearLayout lnrCell;
			ImageView imgIcon;
			TextView txtTitle;
			int iScaledIconSize = (int) (ICON_SIZE * scale);
			final Application appCurrent = m_lstApps.get(p_iPosition);

			// Reuse old view or create a new one?
			if (convertView != null) {
				lnrCell = (LinearLayout) convertView;
				imgIcon = (ImageView) lnrCell.getChildAt(0);
				txtTitle = (TextView) lnrCell.getChildAt(1);
			} else {
				lnrCell = new LinearLayout(m_actParent);				
				lnrCell.setOrientation(LinearLayout.VERTICAL);
				lnrCell.setGravity(Gravity.CENTER);
				
				imgIcon = new ImageView(m_actParent);
				imgIcon.setPadding(m_iPaddingPixels,0,0, 0);
				imgIcon.setAdjustViewBounds(true);
				imgIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
				imgIcon.setLayoutParams(new LinearLayout.LayoutParams(iScaledIconSize, iScaledIconSize));

				txtTitle = new TextView(m_actParent);
				txtTitle.setGravity(Gravity.CENTER_HORIZONTAL);
				
				lnrCell.addView(imgIcon);
				lnrCell.addView(txtTitle);

				// Propagate touchevents to the ViewFlipper in parent view
				imgIcon.setTouchDelegate(m_actParent.getTouchDelegate());
				lnrCell.setTouchDelegate(m_actParent.getTouchDelegate());
				txtTitle.setTouchDelegate(m_actParent.getTouchDelegate());
			}
			// Build the cell
			new _LoadIconTask().execute(imgIcon, appCurrent);
			txtTitle.setText(appCurrent.getName());

			return lnrCell;
		}

		/**
		 * Task to load an icon from cache or server.... This may take a little,
		 * thus need to be put in a async task
		 * 
		 * @author niklas
		 * 
		 */
		private class _LoadIconTask extends AsyncTask<Object, Void, Uri> {
			private ImageView m_oIconView;
			/**
			 * Params: [0] ImageView, [1] Application
			 */
			@Override
			protected Uri doInBackground(Object... params) {
				
				Application appCurrent = (Application) params[1];
				m_oIconView= (ImageView) params[0];
				return appCurrent.getIcon();				
			}
			
			@Override
			protected void onPostExecute(Uri p_oIconUri) {
				m_oIconView.setImageURI(p_oIconUri);
			}
		}

	}

}
